package com.tuuzed.hydrogen.internal;

import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.tuuzed.hydrogen.annotation.Column;
import com.tuuzed.hydrogen.annotation.Ignore;
import com.tuuzed.hydrogen.annotation.Unique;
import com.tuuzed.hydrogen.internal.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public final class Property {
    private String columnName;
    private Field field;
    private boolean nullable;
    private Class<?> javaType;
    private String columnType;
    private boolean unique;

    @Nullable
    static Property create(Field field) {
        // 过滤被标记为Ignore的属性
        if (field.getAnnotation(Ignore.class) != null) return null;
        int modifiers = field.getModifiers();
        // 过滤 static 属性
        if (Modifier.isStatic(modifiers)) return null;
        // 过滤 final 属性
        if (Modifier.isFinal(modifiers)) return null;
        // 过滤不支持的类型
        String type = SQLiteType.getType(field.getClass());
        if (TextUtils.isEmpty(type)) return null;
        return new Property(field);
    }


    private Property(Field field) {
        Column column = field.getAnnotation(Column.class);
        if (column == null) {
            this.columnName = StringUtils.camelToUnderline(field.getName());
            this.nullable = true;
        } else {
            this.columnName = StringUtils.camelToUnderline(column.value());
            this.nullable = column.nullable();
        }
        unique = field.getAnnotation(Unique.class) != null;
        this.field = field;
    }

    public String getColumnName() {
        return columnName;
    }

    public Field getField() {
        return field;
    }

    public String getColumnType() {
        if (columnType == null) {
            columnType = SQLiteType.getType(javaType);
        }
        return columnType;
    }

    public Class<?> getJavaType() {
        if (javaType == null) {
            javaType = field.getType();
        }
        return javaType;
    }

    public Object getValue(Object src) throws IllegalAccessException {
        if (!field.isAccessible()) {
            field.setAccessible(true);
        }
        return field.get(src);
    }

    public void setValue(Object desc, Object value) throws IllegalAccessException {
        if (!field.isAccessible()) {
            field.setAccessible(true);
        }
        field.set(desc, value);
    }

    public boolean isNullable() {
        return nullable;
    }

    public boolean isUnique() {
        return unique;
    }
}